
#include <BSharedMemory>
#include "member_BSharedMemory.h"

using namespace BWE;

#define member					(*(member_BSharedMemory*)_ptr)
#define member_allocate()		_ptr = new member_BSharedMemory(this)
#define member_release()		delete (member_BSharedMemory*)_ptr

BSharedMemory::BSharedMemory()
{
	member_allocate();
}
BSharedMemory::BSharedMemory(const BString& name)
{
	member_allocate();
}
BSharedMemory::~BSharedMemory()
{
#ifdef linux
	if (member.key > -1)
	{
		shmdt(ShareBase);
		shmctl(shm_id, IPC_RMID, NULL);
	}
#endif
#ifdef _WIN32
	if (member.shrmem)
	{
		CloseHandle(member.shrmem);
	}
	UnmapViewOfFile(member.buffer);
#endif
	member_release();
}

bool BSharedMemory::create(int size, IOMode mode)
{
	const BString& name = this->name();
#ifdef _WIN32
	member.shrmem = CreateFileMappingA(0, 0, PAGE_READWRITE, 0, 1024 * 1024, name.cstr());
	member.buffer = MapViewOfFile(member.shrmem, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
#endif

#ifdef linux
	member.size = size;
	const char* name = this->name().cstr();
	if (access(name, F_OK) != 0 && fopen(name, "w") == NULL)
	{
		perror("fopen");
		return false;
	}

	key_t key = ftok(name, 'R');
	if (key == -1)
	{
		perror("ftok");
		return false;
	}

	shm_id = shmget(key, (size, IPC_CREAT | 0666);
	if (shm_id == -1)
	{
		perror("shmget");
		return false;
	}

	member.buffer = (char*)shmat(shm_id, NULL, 0);
	if (member.buffer == (char*)(-1))
	{
		printf("shmat");
		return;
	}

#endif

	return true;
}

bool BSharedMemory::setName(const BString& name)
{
	if (BObject::setName(name))
	{
		return true;
	}
	return false;
}

bool BSharedMemory::attach(IOMode mode)
{
	return false;
}
bool BSharedMemory::detach()
{
	return false;
}
bool BSharedMemory::isAttached() const
{
	return false;
}

void* BSharedMemory::data()
{
	return member.buffer;
}
const void* BSharedMemory::data() const
{
	return member.buffer;
}

BSharedMemory::Error BSharedMemory::error() const
{
	return member.error;
}
BString BSharedMemory::errorString() const
{
	return member.checkError();
}

int BSharedMemory::size() const
{
	return member.size;
}
